package com.jahentao.patentQuery.web.controller;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jahentao.patentQuery.constant.EhCacheKeys;
import com.jahentao.patentQuery.constant.SysUri;
import com.jahentao.patentQuery.exception.TaskException;
import com.jahentao.patentQuery.model.*;
import com.jahentao.patentQuery.model.bean.MessageCode;
import com.jahentao.patentQuery.model.bean.ResultBean;
import com.jahentao.patentQuery.model.page.QueryResult;
import com.jahentao.patentQuery.model.progress.AbstractTask;
import com.jahentao.patentQuery.model.progress.Progress;
import com.jahentao.patentQuery.service.PatentDemandQueryService;
import com.jahentao.patentQuery.service.PatentService;
import com.jahentao.patentQuery.service.PatentSupplyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author jahentao
 * @date 2018/5/1
 * @since 1.0
 */
@Controller
@RequestMapping(SysUri.DEMAND_QUERY)
public class PatentDemandQueryController extends BaseController{

    @Autowired
    private PatentDemandQueryService patentDemandQueryService;
    @Resource
    private CacheManager springCacheManager;
    @Autowired
    private PatentService patentService;
    @Autowired
    private PatentSupplyService patentSupplyService;

    /**
     * 任务编号。
     * <p>有个缺点，重启应用之后，该编号又要从1开始</p>
     * <p>也罢，就限定任务在重启之后，全部失效</p>
     */
    static final AtomicLong TASK_ID_NUMBER = new AtomicLong(1);

    // =============================页面跳转===================================

    @RequestMapping(value = "list")
    public String list() {
        return "admin/demandQuery/list";
    }

    // =============================流程控制===================================

    @ResponseBody
    @RequestMapping(value = "getList",method = RequestMethod.POST)
    public ResultBean getList(@RequestParam(value = "pageNumber", defaultValue = "1")Integer pageNumber,
                              @RequestParam(value = "pageSize", defaultValue = "10")Integer pageSize) {
        ResultBean rb = new ResultBean();

        PatentDemandQueryExample patentDemandQueryExample = new PatentDemandQueryExample();
        patentDemandQueryExample.setOrderByClause("query_time desc");

        // 分页查询
        PageHelper.startPage(pageNumber, pageSize);
        List<PatentDemandQuery> patentDemandQueries = patentDemandQueryService.selectByExample(patentDemandQueryExample);

        Page patentDemandQueriesPage = (Page) patentDemandQueries;
        QueryResult<PatentDemandQuery> queryResult = new QueryResult<PatentDemandQuery>();
        queryResult.setCurrentPage(pageNumber);
        queryResult.setShowNum(pageSize);
        queryResult.setPages(patentDemandQueriesPage.getTotal(), pageSize);
        queryResult.setItems(patentDemandQueries);

        // 返回结果
        rb.setData(queryResult);

        return rb;
    }

    @ResponseBody
    @RequestMapping(value = "deleteIds", method = RequestMethod.POST)
    public ResultBean deleteIds(@RequestParam(value = "ids[]") Long[] ids) {
        ResultBean rb = new ResultBean();

        boolean allSuccess = true;

        for (Long id : ids) {
            final int deleted = patentDemandQueryService.delete(id);
            allSuccess &= deleted > 0;
        }

        if (allSuccess) {
            rb.setMessageCode(MessageCode.SUCCESS);
            rb.setMessage("都删除成功");
        }else {
            rb.setMessageCode(MessageCode.DELETE_FAILURE);
            rb.setMessage("删除失败，或部分删除成功");
        }

        return rb;
    }

    /**
     * 将需求搜索记录转换导入专利提供表中
     * <p>注意时间筛选[start,end]，为方便用户理解和操作，左闭右闭，
     * 但因为内部类访问必须不能修改，end+1天的任务交给前端，后端处理时，仍是[start,end)，左闭右开/p>
     * @param start 起始日期
     * @param end 终止日期
     * @param selectAll
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "convert", method = RequestMethod.POST)
    public ResultBean convert(@RequestParam(value = "start") Date start,
                              @RequestParam(value = "end") Date end,
                              @RequestParam(value = "selectAll", defaultValue = "false")Boolean selectAll) {
        logger.debug("批量转换，是否全部转换：" + Boolean.valueOf(selectAll));
        if (!selectAll) {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            logger.debug("转换时间选择：" + formatter.format(start) + " - " + formatter.format(end));
        }

        ResultBean rb = new ResultBean();
        Map<String, Object> data = new HashMap<String, Object>(1);
        Cache cache = springCacheManager.getCache(EhCacheKeys.ASYNC_DEMAND_QUERY_IMPORT_TO_SUPPLY_TASK_CACHE);

        data.put("taskId", TASK_ID_NUMBER.get());

        try {
            // 执行任务
            patentDemandQueryService.asyncTask(new AbstractTask(TASK_ID_NUMBER.getAndIncrement()) {
                @Override
                public void execute() {
                    logger.debug("task {} is executing. ", this.getId());

                    // 导入转换，不如写个存储过程吧。
                    // 可是写存储过程就不能追踪任务进度了
                    PatentDemandQueryExample example = new PatentDemandQueryExample();
                    if (!selectAll) {
                        example.createCriteria().andQueryTimeBetween(start, end);
                    }
                    // TODO 如果数据量很大，为优化性能，以后可以改为100条的循环查询，再操作
                    List<PatentDemandQuery> patentDemandQueries = patentDemandQueryService.selectByExample(example);
                    Progress progress = this.getProgress();
                    progress.setTotal(patentDemandQueries.size());
                    progress.setCompleted(0);
                    progress.setPercentage(0F);

                    long patentExistNumber = 0L;
                    long patentSupplyConflictNumber = 0L;
                    long success = 0L;

                    for (PatentDemandQuery query : patentDemandQueries) {
                        // 1. 先要插入专利
                        // 如果专利号、专利名称存在，则不插入
                        Patent patent = new Patent();
                        patent.setId(query.getPatentId());
                        patent.setType(query.getPatentId());
                        patent.setName(query.getName());
                        // TODO 使用爬虫爬取状态，将任务加入队列，任务处理后更新状态
                        patent.setLawStatus((byte) 0);

                        // 忽视其他属性，专利号存在即冲突
                        Patent select = patentService.selectByKey(Long.valueOf(query.getPatentId()));
                        if (select != null) {
                            // 插入冲突，已有该专利
                            ++ patentExistNumber;
                        } else {
                            patentService.save(patent);
                        }
                        // 2. 插入patent_supply中
                        // 比对{userid, patent_id, supply_time}，三元组，避免重复的插入记录
                        PatentSupplyExample patentSupplyExample = new PatentSupplyExample();
                        patentSupplyExample.createCriteria().andUserIdEqualTo(query.getUser().getId())
                                                            .andPatentIdEqualTo(query.getPatentId())
                                                            .andSupplyTimeEqualTo(query.getQueryTime());
                        List<PatentSupply> patentSupplies = patentSupplyService.selectByExample(patentSupplyExample);
                        if (patentSupplies == null || patentSupplies.size() == 0) {
                            // 没有重复记录，插入
                            PatentSupply supply = new PatentSupply();
                            supply.setSupplyTime(query.getQueryTime());
                            supply.setPatent(patent);
                            supply.setUser(query.getUser());
                            patentSupplyService.save(supply);
                        } else {
                            // 存在记录，冲突
                            ++ patentSupplyConflictNumber;
                        }

                        ++ success;

                        // 3. 处理过程中，每处理完patent_demand_query中1条记录，在cache中更新记录
                        progress.setCompleted(progress.getCompleted() + 1);
                        // 根据taskId，设置进度
                        logger.debug("task {} 目前进度：{}", getId(), progress.getPercentage());
                        cache.put(getId(), progress.getPercentage());
                    }
                }
            });
        } catch (TaskException e) {
            e.printStackTrace();
        }
        rb.setData(data);
        return rb;
    }

    @ResponseBody
    @RequestMapping(value = "getProgress", method = RequestMethod.POST)
    public ResultBean getProgress(Long taskId) {
        ResultBean rb = new ResultBean();
        Map<String, Object> data = new HashMap<String, Object>(2);
        String process = patentDemandQueryService.getProcess(taskId);
        // 将清理缓存的任务交给查看进度
        if (process.startsWith(Progress.COMPLETE_PERCENTAGE)) {
            patentDemandQueryService.clearCache(taskId);
        }
        data.put("taskId", taskId);
        data.put("progress", process);
        rb.setData(data);
        return rb;
    }
}
